/*
* @file    :drv_adc.c
* @module  :ADC
* @author  :LingFengLu
* @date    :2023-06-06
*/

#include "drv_adc.h"
#include "rf_driver_ll_adc.h"
#include "rf_driver_ll_dma.h"
#include "log.h"
//Constant definition    宏定义
#define USER_SAMPLERATE_MSB       (LL_ADC_SAMPLE_RATE_MSB_4)
#define USER_SAMPLERATE           (LL_ADC_SAMPLE_RATE_0)

#define USER_DATAWIDTH        (LL_ADC_DS_DATA_WIDTH_16_BIT)
#define USER_RATIO            (LL_ADC_DS_RATIO_128)
//Global variable definition    全局变量定义


//Private variable definition    私有变量定义
static uint8 offset_vinm0 = 0;

static uint32 u16_buff[CHANNEL_COUNT] = {0};
//Private function declaration   私有函数申明

static void DMA_Init(void) ;
static void DrvAdc_Init(uint8 u8_AdcChannel) ;



//Public function definition   公共函数定义
void DrvAdc_Init(uint8 u8_AdcChannel)
{
	LL_GPIO_InitTypeDef  gpioinitstruct = {0};
	/* Initialization of the ADC pins */
	LL_AHB_EnableClock(LL_AHB_PERIPH_GPIOB);
	gpioinitstruct.Pin =  LL_GPIO_PIN_1 | LL_GPIO_PIN_3;
	gpioinitstruct.Mode = LL_GPIO_MODE_ANALOG;
	gpioinitstruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
	gpioinitstruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;  
	gpioinitstruct.Pull = LL_GPIO_PULL_NO;  
	LL_GPIO_Init(GPIOB, &gpioinitstruct);  
	
	
	/* Peripheral clock enable */
	LL_APB1_EnableClock(LL_APB1_PERIPH_ADCDIG | LL_APB1_PERIPH_ADCANA);
	
	/* This function must not be called on QFN32 package */
	LL_ADC_LDOEnable(ADC);
	
	
	/* Enable the ADC */
	LL_ADC_Enable(ADC);
	
	/* Configure the sample rate */
	LL_ADC_SetSampleRate(ADC, USER_SAMPLERATE_MSB, USER_SAMPLERATE);
	
	
	/* Configure the Down Sampler data width and ratio */
	LL_ADC_ConfigureDSDataOutput(ADC, USER_DATAWIDTH, USER_RATIO);
	
	/* Configure the operation mode as ADC mode (static/low frequency signal) */
	LL_ADC_SetADCMode(ADC, LL_ADC_OP_MODE_ADC);
	
	/* Start the sampling at end of previous sample */
	LL_ADC_InputSamplingMode(ADC, LL_ADC_SAMPLING_AT_END);
	
	/* Set the length of the conversion sequence as 1 */
	LL_ADC_SetSequenceLength(ADC, LL_ADC_SEQ_LEN_01);
	
	if(u8_AdcChannel == CHANNEL_BATT)
	{
		LL_ADC_SetChannelSeq0(ADC, LL_ADC_CH_BATTERY_LEVEL_DETECTOR);
		LL_ADC_SetVoltageRangeSingleVinp0(ADC, LL_ADC_VIN_RANGE_3V6);
		if(LL_ADC_GET_CALIB_GAIN_FOR_VINPX_3V6() != 0xFFF)
		{
			LL_ADC_SetCalibPoint1Gain(ADC, LL_ADC_GET_CALIB_GAIN_FOR_VINPX_3V6() );
			
			offset_vinm0 = LL_ADC_GET_CALIB_OFFSET_FOR_VINPX_3V6();
			
			LL_ADC_SetCalibPoint1Offset(ADC, offset_vinm0);
			offset_vinm0 = 0;
			
		}
		else 
		{
			LL_ADC_SetCalibPoint1Gain(ADC, LL_ADC_DEFAULT_RANGE_VALUE_3V6);
		}
		LL_ADC_SetCalibPointForSinglePos3V6(ADC, LL_ADC_CALIB_POINT_1);
	}
	
	else if(u8_AdcChannel == CHANNEL_TEMP)
	{
		LL_ADC_SetChannelSeq0(ADC, LL_ADC_CH_TEMPERATURE_SENSOR);
		LL_ADC_SetCalibPoint2Gain(ADC, LL_ADC_DEFAULT_RANGE_VALUE_1V2);
		LL_ADC_SetCalibPointForSinglePos1V2(ADC, LL_ADC_CALIB_POINT_2);
	}
	else if(u8_AdcChannel == CHANNEL_CODE)
	{
		LL_ADC_SetChannelSeq0(ADC, LL_ADC_CH_VINP0_TO_SINGLE_POSITIVE_INPUT);
		LL_ADC_SetVoltageRangeSingleVinp0(ADC, LL_ADC_VIN_RANGE_3V6);
		if(LL_ADC_GET_CALIB_GAIN_FOR_VINPX_3V6() != 0xFFF)
		{
			LL_ADC_SetCalibPoint3Gain(ADC, LL_ADC_GET_CALIB_GAIN_FOR_VINPX_3V6() );
			
			offset_vinm0 = LL_ADC_GET_CALIB_OFFSET_FOR_VINPX_3V6();
			
			LL_ADC_SetCalibPoint3Offset(ADC, offset_vinm0);
			offset_vinm0 = 0;
			
		}
		LL_ADC_SetCalibPointForSinglePos3V6(ADC, LL_ADC_CALIB_POINT_3);
	}
	else if(u8_AdcChannel == CHANNEL_EN_ADC_VMO)
	{
		LL_ADC_SetChannelSeq0(ADC, LL_ADC_CH_VINP1_TO_SINGLE_POSITIVE_INPUT);
		LL_ADC_SetVoltageRangeSingleVinp1(ADC, LL_ADC_VIN_RANGE_3V6);
		if(LL_ADC_GET_CALIB_GAIN_FOR_VINPX_3V6() != 0xFFF)
		{
			LL_ADC_SetCalibPoint4Gain(ADC, LL_ADC_GET_CALIB_GAIN_FOR_VINPX_3V6() );
			
			offset_vinm0 = LL_ADC_GET_CALIB_OFFSET_FOR_VINPX_3V6();
			
			LL_ADC_SetCalibPoint4Offset(ADC, offset_vinm0);
			offset_vinm0 = 0;
			
		}
		LL_ADC_SetCalibPointForSinglePos3V6(ADC, LL_ADC_CALIB_POINT_4);
	}
	DMA_Init() ;
	
	
}

void DrvAdc_DeInit(void)
{
	
}
float ad_value = 0;
uint32 DrvAdc_Single
(
uint8 u8_AdcChannel
)
{
	
	//LL_mDelay(20);
	DrvAdc_Init(u8_AdcChannel) ;
	/* Restart DMA channel */
	LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&u16_buff);
	LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, CHANNEL_COUNT);
	LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
	/* Start ADC conversion */
	LL_ADC_StartConversion(ADC);
	
	while(!LL_ADC_IsActiveFlag_EODS(ADC)&&(!LL_DMA_IsActiveFlag_TC1(DMA1))) ;
	LL_ADC_ClearFlag_EODS(ADC);
	LL_DMA_ClearFlag_TC1(DMA1);
	LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
	
	
	//	ad_value = LL_ADC_DSGetOutputData(ADC);
	if(u8_AdcChannel == CHANNEL_BATT)
	{
		ad_value = (float)LL_ADC_GetADCConvertedValueBatt(ADC, u16_buff[0], USER_DATAWIDTH, offset_vinm0);
		LOG_INFO("batt =%.1f\n",ad_value);
	}
	else if(u8_AdcChannel == CHANNEL_TEMP)
	{
		ad_value = (float)LL_ADC_GetADCConvertedValueTemp(ADC, u16_buff[0], USER_DATAWIDTH)/100.0;
		LOG_INFO("temp =%.1f\n",ad_value);
	}
	else if(u8_AdcChannel == CHANNEL_CODE)
	{
		ad_value = (float)LL_ADC_GetADCConvertedValueSingle(ADC, u16_buff[0], LL_ADC_VIN_RANGE_3V6, USER_DATAWIDTH, offset_vinm0);
		LOG_INFO("code =%.1f\n",ad_value);
	}
	else if(u8_AdcChannel == CHANNEL_EN_ADC_VMO)
	{
		ad_value = (float)LL_ADC_GetADCConvertedValueSingle(ADC, u16_buff[0], LL_ADC_VIN_RANGE_3V6, USER_DATAWIDTH, offset_vinm0);
		LOG_INFO("code =%.1f\n",ad_value);
	}
	return ad_value ;
}








//Private function definition   私有函数定义
static void DMA_Init(void)
{
	/* Init with LL driver */
	/* DMA controller clock enable */
	LL_AHB_EnableClock(LL_AHB_PERIPH_DMA);
	
	/* Configure DMA request MEMTOMEM_DMA1_Channel1 */
	
	/* Set the DMA channel 1 with the ADC Down Sampler output */
	LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_1, LL_DMAMUX_REQ_ADC_DS);
	
	/* Set transfer direction from ADC DS peripheral to RAM memory */
	LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
	
	/* Set priority level */
	LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_HIGH);
	
	/* Set DMA mode */
	LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_NORMAL);
	
	/* Set peripheral increment mode to no increment */
	LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT);
	
	/* Set memory increment mode to increment */
	LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT);
	
	/* Set peripheral data width to 16-bit */
	LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_HALFWORD);
	
	/* Set memory data width to 16-bit */
	LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_HALFWORD);
	
	/* Set DMA transfer addresses of source and destination */
	LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_1,
			       LL_ADC_GetOutputDataRegDS(ADC),
			       (uint32_t)&u16_buff,
			       LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
	
	/* Set DMA transfer size */
	LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, CHANNEL_COUNT);
	
	/* Enable DMA transfer complete/error interrupts */
	LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
	
	/* Start the DMA transfer */
	LL_ADC_DMAModeDSEnable(ADC);
	LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
	
}

